#include <functional>
#include "outline/pin.h"

namespace outline {

void remove_overlapped_pins(pin_vector & pins, 
	point<float> const & center, float radius)
{
	pin_vector::iterator i;
	for (i = pins.begin(); i != pins.end(); ) {
		if (square(center - i->center) < square(radius + i->radius))
			i = pins.erase(i);
		else
			++i;
	}
}

struct first_index_of_area_is_less : std::binary_function<pin, pin, bool>
{
	bool operator () (pin const & lhs, pin const & rhs) const {
		assert (!lhs.indeces.empty());
		assert (!rhs.indeces.empty());
		return lhs.indeces[0] < rhs.indeces[0];
	}
};

template <typename T>
void add_pin(pin_vector & pins, std::vector< point<T> > const & polyline, 
	point<float> const & center, float radius, junc_type type)
{
	pin a;
	a.center = center;
	a.radius = radius;
	a.type = type;
	double rr = radius * radius;
	unsigned n;
	bool first_space = true;
	for (n = 0; n+1 < polyline.size(); ++n) {
		if (square(center - point<float>(polyline[n])) <= rr) {
			if (!a.indeces.empty() && n != a.indeces.back()+1) {
				if (a.indeces[0] != 0 || !first_space)
					throw std::runtime_error("The area must contain only ONE continues piece of nodes from the polyline.");
				first_space = false;
			}
			a.indeces.push_back(n);
		}
	}

	if (a.indeces.empty()) 
		throw std::runtime_error("The area contains no nodes of the polyline.");

	//check overlapping
	outline::index_vector_type intsec(a.indeces.size());
	for (n = 0; n < pins.size(); ++n) {
		if (std::set_intersection(
			a.indeces.begin(), a.indeces.end(),
			pins[n].indeces.begin(), pins[n].indeces.end(),
			intsec.begin()) != intsec.begin()) 
		{
			throw std::runtime_error("The area shares some nodes of polyline with another area.");
		}
	}

	pins.push_back(a);
	std::inplace_merge(pins.begin(), pins.end()-1, pins.end(), first_index_of_area_is_less());
}

#define INSTANTIATE(T) \
template \
void add_pin(pin_vector & pins, std::vector< point<T> > const & polyline,  \
	point<float> const & center, float radius, junc_type type);

INSTANTIATE(unsigned short)
INSTANTIATE(short)
INSTANTIATE(int)
INSTANTIATE(float)
INSTANTIATE(double)

#undef INSTANTIATE

} //namespace outline
